Jetpack Compose for Desktop 初体验
随着去年底 Jetpack Compose for Desktop 的正式发布, Compose 终于迈向了跨平台的道路,再配合 Kotlin MultiPlatform ,前景不可限量。Kotlin 生态的不断壮大,对于广大 Android 开发者来说也是一个福音。
从 https://github.com/JetBrains/compose-jb 中可以获得项目源码和Sample,本文基于其中一些 Sample 来一个上手体验。
运行环境如下:
macOS Catalina 10.15.7 IntelliJ IDEA 2020.3 (Community Edition) AdoptOpenJDK 14.0.2 Kotlin 1.4.20 Desktop Compose 0.2.0-build132
1. 显示图片
fun main() {
Window {
Image(
bitmap = TODO("Create ImageBitmap"),
modifier = Modifier.fillMaxSize()
)
}
}
创建 ImageBitmap有以下几种方法:
1.1 从Resource中加载
从Resource目录中加载图片
bitmap = imageResource("sample.png"),
注意 imageResource 是 @Composable 函数,只能在 @Composable 中调用。
除了png等一般图片外,还可以加载xml格式的矢量图,此时需要使用 vectorXmlResource 方法
imageVector = vectorXmlResource("images/compose-logo.xml"),
1.2 从Device加载
从设备的指定路径中加载图片文件
bitmap = Image.makeFromEncoded(File("sample.png").readBytes()).asImageBitmap(),
1.3 Canvas绘制
除了加载资源外,也可以直接在Canvas上绘制图片。例子比较长,此处省略。
2. APP图标
创建APP窗口的Window时,可以指定APP图标
fun main() {
Window(icon = ImageIO.read(File("sample.png"))) {
}
}
3. 托盘图标
在onActive中可以设置系统托盘图标,menu
必须设置否则无法显示
fun main() {
Window {
onActive {
val tray = Tray().apply {
icon(ImageIO.read(File("sample.png")))
menu(
MenuItem(
name = "Quit App",
onClick = { AppManager.exit() }
)
)
}
onDispose {
tray.remove()
}
}
}
}
4. 滚动条
Scrollbar的显示至少要完成以下配置:
fun main() {
Window {
Box {
val stateVertical = rememberScrollState(0f)
val stateHorizontal = rememberScrollState(0f)
ScrollableColumn(scrollState = stateVertical) {
ScrollableRow(scrollState = stateHorizontal) {
Column {
for (item in 0..100) {
Box { Text("Item in ScrollableColumn #$item") }
}
}
}
}
VerticalScrollbar(adapter = rememberScrollbarAdapter(stateVertical))
HorizontalScrollbar(adapter = rememberScrollbarAdapter(stateHorizontal))
}
}
}
Compose是基于State驱动的,所以需要通过 rememberScrollState() 为各个滚动条创建 ScrollState 将创建的state传递给 ScrollableColumn 和 ScrollableRow 通过 rememberScrollbarAdapter(scrollState: ScrollState) 创建 ScrollAdapter 将adapter传递给 Scrollbar
5. 鼠标事件
在UI中通过Modifier.clickable
监听鼠标的Click事件回调
5.1 Click事件
Box(
modifier = Modifier.clickable(
onClick = {
},
onDoubleClick = {
},
onLongClick = {
}
)
)
5.2 鼠标移动
Modifier.pointerMoveFilter
监听鼠标移动
Box(
modifier = Modifier.pointerMoveFilter(
onMove = {
false
},
onEnter = {
false
},
onExit = {
false
}
)
)
onMove: 获取鼠标当前坐标 onEnter: 鼠标进入此View的区域 onExit: 鼠标移除此区域
6 键盘事件
下面的例子中,我们在 TextField 中输入的文字通过 “Cmd+Enter” 会出现在上面 Text 的 "Apply text:"中;通过 "Cmd+R" 会清空 Text
@OptIn(ExperimentalKeyInput::class)
fun main() = Window {
MaterialTheme {
var applyText by remember { mutableStateOf("") }
var inputText by remember { mutableStateOf("") }
Column {
Text("Apply text: $applyText")
TextField(
value = inputText,
onValueChange = { inputText = it },
modifier = Modifier.shortcuts {
on(Key.CtrlLeft + Key.Enter) {
applyText = inputText
inputText = ""
}
on(Key.CtrlLeft + Key.R) {
applyText = ""
inputText = ""
}
}
)
}
}
}
KeyInut 相关的API目前还是Experimental
状态,后期有可能会变化,需注意。
另外,通过 AppWindow 的 keyboard 属性,可以定义一些全局快捷键,如下:
AppWindow().also {
it.keyboard.setShortcut(Key.Escape) {
it.close()
}
}.show {
}
7. 兼容Java Swing
Swing 是我们常用的桌面端GUI库,Compose可以在Swing中使用,ComposePanel 可以作为Composable的容器使用:
fun main() {
val window = JFrame()
val composePanel = ComposePanel()
window.contentPane.add(composePanel, BorderLayout.CENTER)
composePanel.setContent {
Box {
Text("text")
}
}
window.setSize(100, 100)
window.isVisible = true
}
最后
虽然Kotlin-Multiplatform在跨平台领域早已显露头角,但多是用于逻辑层,如今Compose的出现把UI层的短板也补齐了,这将大大提升Kotlin在跨平台领域的整体竞争力,对Kotlin的未来无限看好!
https://github.com/JetBrains/compose-jb/tree/master/tutorials
↓关注公众号↓ | ↓添加微信交流↓ |
---|---|